﻿using CMS6Tools.Common.Utility;
using Microsoft.TeamFoundation.WorkItemTracking.Client;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using WeifenLuo.WinFormsUI.Docking;
using Common = global::Common;

namespace CMS6Tools.Management
{
    public partial class ReleasePackageForm : DockContent
    {
        const string DefaultIgnoredFolderCopyPattern = Util.DefaultIgnoredFolderCopyPattern;

        private global::Common.Logging.ILog Logger = null;

        #region Ctor
        public ReleasePackageForm()
        {
            InitializeComponent();
            Logger = new global::Common.Logging.Simple.ConsoleOutLogger(this.GetType().FullName, global::Common.Logging.LogLevel.All, true, false, "hh:mm:ss.fff");
        }
        #endregion

        #region Properties
        protected string EnterpriePackageSelectedPath { get; private set; }
        protected string CMS6ReleaseFTPSelectedPath { get; private set; }
        protected string CMS6ReleaseTFSSelectedPath { get; set; }
        protected string SelectedIteration { get; private set; }
        #endregion

        #region Form Load
        private void ReleasePackageForm_Load(object sender, EventArgs e)
        {
            #region Enterprise
            EnterpriePackageSelectedPath = @"E:\Published\CMS6 Enterprise";
            CMS6SourceFolderTextBox.Text = @"D:\Project\CMSCollection\CMS 6\CMS 6\branches\RC\CMS6_RC";
            CMS6ReleaseTextBox.Text = @"E:\Published\CMS6\CMS6";
            TfsIterationUserControl.ShownLevel = 1;
            TfsIterationUserControl.MultipleSelect = false;
            TfsIterationUserControl.SelectedChanged += TfsIterationUserControl_SelectedChanged;
            TfsIterationUserControl.LoadTfs();
            #endregion

            #region FTP to TFS
            CMS6ReleaseFTPSelectedPath = @"\\gold\LocalUser\ctxusftp\CMS6 Release\CMS6";
            CMS6ReleaseTFSSelectedPath = @"D:\Project\CMSCollection\CMS 6\CMS 6\tags";
            #endregion

            ChangeEnterprisePackageFolder();
        }
        #endregion

        #region Enterprise
        private void SelectFolderButton_Click(object sender, EventArgs e)
        {
            if (!string.IsNullOrEmpty(CMS6EnterpriseFolderTextBox.Text))
                CMS6EnterpriseFolderBrowserDialog.SelectedPath = CMS6EnterpriseFolderTextBox.Text;
            CMS6EnterpriseFolderBrowserDialog.ShowDialog();
            EnterpriePackageSelectedPath = CMS6EnterpriseFolderBrowserDialog.SelectedPath;            
            ChangeEnterprisePackageFolder();
        }

        private void MakeEnterprisePackageButton_Click(object sender, EventArgs e)
        {
            if (TfsIterationUserControl.SelectedNode == null)
            {
                MessageBox.Show("Please select an iteration first!");
                return;
            }

            var oldWriter = Console.Out;
            Console.SetOut(new TextBoxWriter(LogTextBox));
            var path = CMS6EnterpriseFolderTextBox.Text.TrimEnd('\\') + "\\";

            if (!Directory.Exists(path))
                Directory.CreateDirectory(path);

            // Batch File
            var batchFileFolder = Path.Combine(Path.GetDirectoryName(this.GetType().Assembly.Location), @"Data\Release\Batchfiles");
            var batchFiles = Directory.GetFiles(batchFileFolder, "*.bat");
            foreach (var batchFile in batchFiles)
            {
                File.Copy(batchFile, Path.Combine(path, Path.GetFileName(batchFile)), true);
            }

            // DLLs
            var VisionDLLfolder = Path.Combine(path, "VisionDLL");
            if (!Directory.Exists(VisionDLLfolder))
                Directory.CreateDirectory(VisionDLLfolder);
            var visionDLLFileNames = new string[] { "Vision.Api.Common.dll", "Vision.Api.Mvc.dll", 
                                                    "Vision.Cms.ActiveDirectoryServices.dll", "Vision.Cms.Common.dll",
                                                    "Vision.Cms.EntityFramework.dll", "Vision.Cms.ObjectContainer.dll",
                                                    "Vision.Search.Api.dll", "Vision.Web.Common.dll"};
            foreach (var dllfile in visionDLLFileNames)
            {
                var dllFileSourcePath = Path.Combine(CMS6ReleaseTextBox.Text, "bin", dllfile);
                if (File.Exists(dllFileSourcePath))
                    File.Copy(dllFileSourcePath, Path.Combine(VisionDLLfolder, dllfile), true);
            }

            // CMS6 source code
            var CMS6folder = Path.Combine(path, "CMS6");
            if (!Directory.Exists(CMS6folder))
                Directory.CreateDirectory(CMS6folder); 
            
            var cms6EnterpriseFolder=Path.Combine(path ,"CMS6");
            CMS6Tools.Common.Utility.FileSystemUtility.CopyDirectory(CMS6SourceFolderTextBox.Text, cms6EnterpriseFolder, Logger: Logger, excludedFolderPattern: DefaultIgnoredFolderCopyPattern);
                
            var worker = new CMS6EnterpriseWorker(cms6EnterpriseFolder,
                                                  Path.Combine(path , "VisionDLL"),
                                                  Path.Combine(path , "CMS6_Enterprise"),
                                                  ignoredFolderPattern: DefaultIgnoredFolderCopyPattern);
            worker.Logger = Logger;
            worker.Do();

            // Run batch file: "ClearDLL_Zip_CMS6.bat"
            var ClearDLL_Zip_CMS6BathFile = Path.Combine(path, "ClearDLL_Zip_CMS6.bat");
            if (File.Exists(ClearDLL_Zip_CMS6BathFile)) 
                Process.Start(ClearDLL_Zip_CMS6BathFile);  

            // Run batch file: "ClearDLL_Zip_CMS6_Enterprise.bat"
            var ClearDLL_Zip_CMS6_EnterpriseFile = Path.Combine(path, "ClearDLL_Zip_CMS6_Enterprise.bat");
            if (File.Exists(ClearDLL_Zip_CMS6_EnterpriseFile))
                Process.Start(ClearDLL_Zip_CMS6_EnterpriseFile);

            Console.SetOut(oldWriter);
            MessageBox.Show("Succeed!");
        }
        
        void TfsIterationUserControl_SelectedChanged(object sender, Node selectedValue)
        {
            SelectedIteration = selectedValue.Name.Substring("Release".Length).Trim();   
            
            ChangeEnterprisePackageFolder();
        }

        protected void ChangeEnterprisePackageFolder()
        {
            CMS6EnterpriseFolderTextBox.Text = string.Format("{0}\\{1}", EnterpriePackageSelectedPath.TrimEnd('\\'), SelectedIteration);
            CMS6ReleaseFTPFolderTextBox.Text = string.Format("{0}\\{1}", CMS6ReleaseFTPSelectedPath.TrimEnd('\\'), SelectedIteration);
            CMS6ReleaseTFSFolderTextBox.Text = string.Format("{0}\\{1}", CMS6ReleaseTFSSelectedPath.TrimEnd('\\'), SelectedIteration);
            CMS6ReleaseEnterpriseTextBox.Text = CMS6EnterpriseFolderTextBox.Text;
        }

        private void TfsIterationUserControl_Load(object sender, EventArgs e)
        {

        }
        #endregion

        #region FTP to TFS
        private void CMS6FTPtoTFSButton_Click(object sender, EventArgs e)
        {
            if (TfsIterationUserControl.SelectedNode == null)
            {
                MessageBox.Show("Please select an iteration first!");
                return;
            }

            var cms6ReleaseFTPFolderPath = CMS6ReleaseFTPFolderTextBox.Text.Trim();
            if (!Directory.Exists(cms6ReleaseFTPFolderPath))
            {
                MessageBox.Show("CMS6 FTP folder doesn't exist!");
                return;
            }

            var oldWriter = Console.Out;
            Console.SetOut(new TextBoxWriter(LogTextBox)); 

            var cms6ReleaseTFSFolderPath = CMS6ReleaseTFSFolderTextBox.Text.Trim();
            if (!Directory.Exists(cms6ReleaseTFSFolderPath))
                Directory.CreateDirectory(cms6ReleaseTFSFolderPath);

            var hotfixPath = GetOrCreateDirectory(cms6ReleaseTFSFolderPath, "Hotfix");

            var patchPath = GetOrCreateDirectory(cms6ReleaseTFSFolderPath, "Patch");

            var sourcePath = GetOrCreateDirectory(cms6ReleaseTFSFolderPath, "Source");

            var releasePath = GetOrCreateDirectory(cms6ReleaseTFSFolderPath, "Release");
             
            ExtractReleasePackage(Path.Combine(cms6ReleaseFTPFolderPath, "Release", "Released_ActiveDirectory.zip"), GetOrCreateDirectory(cms6ReleaseTFSFolderPath, "Release", "AD"));

            ExtractReleasePackage(Path.Combine(cms6ReleaseFTPFolderPath, "Release", "Released_API_SDK.zip"), GetOrCreateDirectory(cms6ReleaseTFSFolderPath, "Release", "API"));

            ExtractReleasePackage(Path.Combine(cms6ReleaseFTPFolderPath, "Release", "Released_VisionAPI.zip"), GetOrCreateDirectory(cms6ReleaseTFSFolderPath, "Release", "API"));

            CMS6Tools.Common.Utility.FileSystemUtility.CopyDirectory(Path.Combine(CMS6ReleaseEnterpriseTextBox.Text,"CMS6_Enterprise"), GetOrCreateDirectory(cms6ReleaseTFSFolderPath, "Release", "CMS6", "_Enterprise", "Source"), Logger: Logger, excludedFolderPattern: DefaultIgnoredFolderCopyPattern);

            var releaseCMS6Folder = ExtractReleasePackage(Path.Combine(cms6ReleaseFTPFolderPath, "Release", "CMS60 UPDATE SQL.zip"), GetOrCreateDirectory(cms6ReleaseTFSFolderPath, "Release", "CMS6"));
            RenameFolder(releaseCMS6Folder, "CMS60 UPDATE SQL", "_CMS60 UPDATE SQL");

            ExtractReleasePackage(Path.Combine(cms6ReleaseFTPFolderPath, "Release", "Released_CMS6.zip"), GetOrCreateDirectory(cms6ReleaseTFSFolderPath, "Release", "CMS6"));

            ExtractReleasePackage(Path.Combine(cms6ReleaseFTPFolderPath, "Release", "Released_Components.zip"), GetOrCreateDirectory(cms6ReleaseTFSFolderPath, "Release", "CMS6"));

            ExtractReleasePackage(Path.Combine(cms6ReleaseFTPFolderPath, "Release", "Released_Licenses.zip"), GetOrCreateDirectory(cms6ReleaseTFSFolderPath, "Release", "CMS6"));

            ExtractReleasePackage(Path.Combine(cms6ReleaseFTPFolderPath, "Release", "Released_Project.zip"), GetOrCreateDirectory(cms6ReleaseTFSFolderPath, "Release", "CMS6"));
            RenameFolder(releaseCMS6Folder, "Released_Project", "Project");

            ExtractReleasePackage(Path.Combine(cms6ReleaseFTPFolderPath, "Release", "To IT Team", "Vision Search", "Released_SEARCH.zip"), GetOrCreateDirectory(cms6ReleaseTFSFolderPath, "Release", "Search"));

            ExtractReleasePackage(Path.Combine(cms6ReleaseFTPFolderPath, "Release", "To IT Team", "Vision Search", "Released_Search_Licenses.zip"), GetOrCreateDirectory(cms6ReleaseTFSFolderPath, "Release", "Search"));

            ExtractReleasePackage(Path.Combine(cms6ReleaseFTPFolderPath, "Release", "To IT Team", "Vision Search", "Search UPDATE SQL.zip"), GetOrCreateDirectory(cms6ReleaseTFSFolderPath, "Release", "Search"));

            ExtractReleasePackage(Path.Combine(cms6ReleaseFTPFolderPath, "Release", "To IT Team", "VMC", "Released_VMC.zip"), GetOrCreateDirectory(cms6ReleaseTFSFolderPath, "Release", "VMC"));

            ExtractReleasePackage(Path.Combine(cms6ReleaseFTPFolderPath, "Release", "To IT Team", "VMC", "LIVE VMC UPDATE SQL.zip"), GetOrCreateDirectory(cms6ReleaseTFSFolderPath, "Release", "VMC"));

            ExtractReleasePackage(Path.Combine(cms6ReleaseFTPFolderPath, "Release", "To IT Team", "VMC", "DEV VMC UPDATE SQL.zip"), GetOrCreateDirectory(cms6ReleaseTFSFolderPath, "Release", "VMC"));
            
            // To Do. Source Code Branch.


            Console.SetOut(oldWriter);
            MessageBox.Show("Succeed!");
        }
        #endregion

        #region Help Methods
        protected string GetOrCreateDirectory(params string[] paths)
        {
            if (paths.Any())
            {
                var currentPath = paths.First();
                var index = 1;
                var count = paths.Count();
                do
                {
                    if (!Directory.Exists(currentPath))
                    {
                        Directory.CreateDirectory(currentPath);
                        Logger.Info(string.Format("Create Folder:{0}", currentPath));
                    }
                    if (index < count)
                        currentPath = Path.Combine(currentPath, paths[index++]);
                    else
                        break;
                } while (true);
                return currentPath;
            }
            return string.Empty;
        }

        protected string ExtractReleasePackage(string zipFileFilePath, string outputFolder)
        {
            Logger.Info(string.Format("Extract Zip File:{0} to {1}", zipFileFilePath, outputFolder));
            ZipUtility.Extract(zipFileFilePath, outputFolder);

            return outputFolder;
        }

        protected string RenameFolder(string parentFolderPath, string fromFolderName, string toFolderName)
        {
            var toFolderPath = Path.Combine(parentFolderPath, toFolderName);
            var fromDirectoryInfo = new DirectoryInfo(Path.Combine(parentFolderPath, fromFolderName));
            if (fromDirectoryInfo.Exists)
            {
                if (Directory.Exists(toFolderPath))
                    Directory.Delete(toFolderPath);
                fromDirectoryInfo.MoveTo(toFolderPath);
                return toFolderPath;
            }
            return fromDirectoryInfo.FullName;
        }
        #endregion

    }
}
